package task

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"io"
	"log"
	"net"
	"strconv"
	"time"
)

//TCP服务端
type TcpServer struct {
	flow      *FlowTask
	port      string //监听端口
	connType  string //连接类型
	dataLen   int    //报文长度
	dataType  string //数据类型
	separator string //分隔符
}

//创建一个服务
func NewTcpServer(data string) (*TcpServer, error) {
	server := new(TcpServer)
	flow, err := NewFlowTask(nil, data)
	if err != nil {
		fmt.Println("定时任务流程配置不正确！", err)
		return nil, err
	}
	server.flow = flow
	node := flow.Data.NodeList[0]
	server.port = node.Content["port"]           //监听地址
	server.connType = node.Content["connType"]   //长连接/短连接
	dataLen := node.Content["dataLen"]           //固定头长
	server.dataType = node.Content["dataType"]   //数据类型
	server.separator = node.Content["separator"] //分隔符

	if dataLen != "" {
		server.dataLen, _ = strconv.Atoi(dataLen)
	}

	return server, nil
}

//启动一个服务
func (m *TcpServer) Start() error {
	var addr *net.TCPAddr
	addr, _ = net.ResolveTCPAddr("tcp", ":"+m.port)
	listener, err := net.ListenTCP("tcp", addr)
	if err != nil {
		fmt.Println("TCP Server监听:", err)
		return err
	}
	log.Printf("TCP服务监听地址：%s\n", addr.String())
	defer listener.Close()
	for {
		conn, err := listener.AcceptTCP()
		if err != nil {
			fmt.Println(err)
			continue
		}
		serve := Service{
			conn:     conn,
			flow:     m.flow,
			input:    make(map[string]interface{}, 0),
			connType: m.connType,
			dataLen:  m.dataLen,
		}
		go serve.Serve()
	}
}

//TCP服务业务处理结构体
type Service struct {
	conn     *net.TCPConn
	flow     *FlowTask
	input    map[string]interface{}
	connType string
	dataLen  int //报文长度
}

//TCP服务业务执行业务处理
func (m *Service) Serve() {
	if m.connType == "long" {
		go m.Heartbeat()
	} else {
		defer m.conn.Close()
	}
	err := m.Read()
	if err != nil {
		log.Println(err)
		return
	}
	list := m.flow.Data.NodeList
	err = m.flow.Next(list[0].Id)
	if err != nil {
		return
	}
	m.flow.wg.Wait()
	var node Node
	for _, n := range list {
		if n.NodeType == "END" {
			node = n
			break
		}
	}

	successCode := node.Content["successCode"]
	dataKey := node.Content["dataKey"]
	dataType := node.Content["dataType"]
	result := m.flow.BindInput(node.Params)
	switch dataType {
	case "bytes":
		for _, v := range result {
			bs, ok := v.([]byte)
			if !ok {
				bs, _ := json.Marshal(gin.H{"code": "5000", "msg": "响应参数绑定与响应类型不匹配"})
				m.Error(string(bs))
				return
			}
			m.Write(string(bs))
		}
	default:
		if dataKey != "" {
			bs, _ := json.Marshal(gin.H{"code": successCode, "msg": "成功", dataKey: result})
			m.Write(string(bs))
		} else if len(result) == 1 {
			for k, v := range result {
				if dataType == "string" {
					m.Write(v.(string))
				} else {
					bs, _ := json.Marshal(gin.H{"code": successCode, "msg": "成功", k: v})
					m.Write(string(bs))
				}
				break
			}
		} else {
			bs, _ := json.Marshal(result)
			m.Write(string(bs))
		}
	}
}

//TCP服务业务处理读取数据包
func (m *Service) Read() error {
	size := make([]byte, m.dataLen)
	_, err := m.conn.Read(size)
	if err != nil {
		log.Println("TCP服务：读取报文长度出错!", err)
		m.Error("TCP服务：读取报文长度出错!")
		return err
	}

	length, err := strconv.ParseInt(string(size), 10, 64)
	if err != nil {
		log.Println("TCP服务：数据长度格式不正确！", err)
		m.Error("TCP服务：数据长度格式不正确！")
		return err
	}
	data := make([]byte, length)
	n, err := m.conn.Read(data)
	if err != nil && err != io.EOF {
		log.Println("TCP服务：读取数据错误！", err)
		m.Error("TCP服务：读取数据错误！")
		return err
	}

	for int64(n) < length {
		nn, err := m.conn.Read(data)
		if err != nil {
			break
		}
		n += nn
	}
	fmt.Println("有客户端请求服务：", string(data))
	err = json.Unmarshal(data, &m.input)
	if err != nil {
		log.Println("TCP服务：数据格式不正确！", err)
		m.Error("TCP服务：数据格式不正确！")
		return err
	}
	return nil
}

//TCP服务业务处理发送数据包
func (m *Service) Write(data string) {
	if m.dataLen != 0 {
		s := len([]byte(data))
		len := fmt.Sprintf("%0"+strconv.Itoa(m.dataLen)+"d", s)
		m.conn.Write([]byte(len))
	}
	m.conn.Write([]byte(data))
}

//TCP服务长连接心跳包
func (m *Service) Heartbeat() {
	ticker := time.NewTicker(time.Minute * 1)
	go func() {
		for _ = range ticker.C {
			m.Write("0000")
		}
	}()
}

//TCP服务业务处理失败时返回错误消息
func (m *Service) Error(err string) {
	result := make(map[string]string)
	result["error"] = err
	bs, _ := json.Marshal(result)
	m.Write(string(bs))
}

func (m *Service) Stop() {
	m.conn.Close()
}

//TCP客户端========================================
type TcpClient struct {
	flow     *FlowTask
	conn     *net.TCPConn
	ip       string
	port     string
	connType string
	dataLen  int
	dataType string
	input    map[string]interface{}
}

//TCP客户端创建
func NewTcpClient(flow *FlowTask) *TcpClient {
	m := new(TcpClient)
	m.flow = flow
	return m
}

//TCP客户端执行任务
func (m *TcpClient) Handler(node *Node) error {
	m.ip = node.Content["ip"]
	m.port = node.Content["port"]
	m.connType = node.Content["connType"]
	dataLen := node.Content["dataLen"]
	m.dataType = node.Content["dataType"]

	if dataLen != "" {
		m.dataLen, _ = strconv.Atoi(dataLen)
	}
	m.input = m.flow.BindInput(node.Params)
	var err error
	tcpAddr, _ := net.ResolveTCPAddr("tcp4", fmt.Sprintf("%s:%s", m.ip, m.port))
	m.conn, err = net.DialTCP("tcp", nil, tcpAddr)
	if err != nil {
		return errors.New("TCP客户端：客户端连接失败！" + err.Error())
	}
	if m.connType == "long" {
		//go m.Heartbeat()
	} else {
		defer m.conn.Close()
	}
	bs, err := json.Marshal(m.input)
	if err != nil {
		return errors.New("TCP客户端：准备请求数据失败！" + err.Error())
	}
	m.Write(string(bs))
	err = m.Read(node)
	return err
}

//TCP服务业务处理读取数据包
func (m *TcpClient) Read(node *Node) error {
	size := make([]byte, m.dataLen)
	_, err := m.conn.Read(size)
	if err != nil {
		return errors.New("TCP客户端：读取数据长度失败！" + err.Error())
	}
	length, err := strconv.Atoi(string(size))
	if err != nil {
		return errors.New("TCP客户端：数据长度格式不正确！" + err.Error())
	}
	data := make([]byte, length)
	l, err := m.conn.Read(data)
	if err != nil {
		return errors.New("TCP客户端：读取数据错误！" + err.Error())
	}
	for l < length {
		n, err := m.conn.Read(data)
		if err != nil {
			return errors.New("TCP客户端：读取数据错误！" + err.Error())
		}
		l += n
	}
	switch m.dataType {
	case "bytes":
		m.flow.outByte[node.Id] = data
	case "string":
		m.flow.outText[node.Id] = string(data)
	case "object":
		result := make(map[string]interface{}, 0)
		err = json.Unmarshal(data, &result)
		if err != nil {
			return errors.New("TCP客户端：数据格式不正确！" + err.Error())
		}
		m.flow.out[node.Id] = result
	case "list":
		result := make([]map[string]interface{}, 0)
		err = json.Unmarshal(data, &result)
		if err != nil {
			return errors.New("TCP客户端：数据格式不正确！" + err.Error())
		}
		m.flow.outList[node.Id] = result
	}
	return nil
}

//TCP服务业务处理发送数据包
func (m *TcpClient) Write(data string) {
	if m.dataLen != 0 {
		s := len([]byte(data))
		len := fmt.Sprintf("%0"+strconv.Itoa(m.dataLen)+"d", s)
		m.conn.Write([]byte(len))
	}
	m.conn.Write([]byte(data))
}
